﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;
using FormCommon;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;

public enum FormMode
{
    Insert,
    Update,
    View,
    Browse
}

public partial class FormBase : DockContent
{
    private FormMode _formMode;

    public FormMode Mode
    {
        get { return _formMode; }
        set { _formMode = value; }
    }

    internal bool HandleEsc;
    internal bool HandleLookup;


    #region "Process Hot Key"

    private Dictionary<Keys, object> m_lstHotKey = new Dictionary<Keys, object>();
    private void HotKey_Init(object ctlInit)
    {
        if (ctlInit is ToolStrip)
        {
            foreach (ToolStripItem ctlChild in ((ToolStrip)ctlInit).Items)
            {
                if (ctlChild is ToolStripButton)
                {
                    HotKey_Init(ctlChild);
                }
            }
        }
        else if (ctlInit is Panel)
        {
            foreach (Control ctlChild in (ctlInit as Panel).Controls)
            {
                if (ctlChild is Button)
                {
                    HotKey_Init(ctlChild);
                }
            }
        }
        else
        {
            if (!((ctlInit as Control).Text.Contains("(") && (ctlInit as Control).Text.Contains(")")))
            {
                //Assign system hot key init 
                string sKeyItem = "HK_" + (ctlInit as Control).Name.Substring(3).Split(new string[]{"_"},StringSplitOptions.None)[0];
                if ((FormGlobals.HotKeyData != null) && FormGlobals.HotKeyData.HasItem(sKeyItem))
                {
                    ((Control)ctlInit).Text += " (" + FormGlobals.HotKeyData.Item(sKeyItem) + ")";
                }
            }
            string sText = ((Control)ctlInit).Text;
            sText = Regex.Replace(sText, ".*\\s\\((.*)\\)", "$1");
            if (sText != ((Control)ctlInit).Text)
            {
                Keys key = FormGlobals.Keys_Parse(sText);
                if (key > 0)
                    m_lstHotKey.Add(key, ctlInit);
            }
        }
    }

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        //Key lookup process
        if (keyData == FormGlobals.CS_LOOKUP_KEY)
        {
            //Textbox lookup process
            //If TypeOf Me.ActiveControl.Tag Is FormControlExt _
            //AndAlso DirectCast(Me.ActiveControl.Tag, FormControlExt).Lookup _
            //Then
            if (HandleLookup)
            {
                return true;
            }
        }
        //Shortcut process
        if (m_lstHotKey.ContainsKey(keyData) && (m_lstHotKey[keyData] as Control).Enabled)
        {
            (m_lstHotKey[keyData] as Button).PerformClick();
            return true;
        }
        //Esc process
        if (keyData == Keys.Escape && this.MdiParent == null && !HandleEsc)
        {
            this.Close();
            return true;
        }
        //Allow update only in debug mode
#if (Debug)
	if (keyData == Keys.Shift + Keys.F6) {
		if (Message_Confirm("Update all button command data")) {
			//Update command button
			Control pnlCommand = Find_Control(this, "pnlCommand");
			if ((pnlCommand != null)) {
				Button_BuildAll(pnlCommand);
			}
		}
	}
#endif
        return base.ProcessCmdKey(ref msg, keyData);
    }
    #endregion

    //=======================================================
    //Service provided by Telerik (www.telerik.com)
    //Conversion powered by NRefactory.
    //Twitter: @telerik
    //Facebook: facebook.com/telerik
    //=======================================================


    #region "Override function"

    public virtual void Show_Form()
    {
        //Must Override for auto show form when click menu
    }

    public virtual DialogResult Show_Form(object input)
    {
        //Must Override for auto show form when call from another
        return base.ShowDialog();
    }

    protected virtual void Init_Control()
    {
        //Must Override for init control
    }

    protected virtual void Recall_Form()
    {
        //Must Override for reload data when recall form
    }

    protected virtual void Control_Validated(object sender, System.EventArgs e)
    {
        //Must Override for handle custom control valid
    }

    protected virtual void PageIndex_Changed(Int32 newIndex)
    {
        //Must Override for handle page control page index change
    }

    protected virtual void PageSize_Changed(Int32 newSize)
    {
        //Must Override for handle page control page size change
    }

    #endregion

    //Protected Overloads Function ShowDialog() As DialogResult
    public new DialogResult ShowDialog()
    {
        FormGlobals.Form_InitDialog(this);
        //
        m_initDialog = true;
        //FormGlobals.App_ProgressShow(new MethodInvoker(Init_Form));
        Init_Form();
        //
        return base.ShowDialog();
    }

    protected new void Show()
    {
        Show(WeifenLuo.WinFormsUI.Docking.DockState.Document);
    }

    protected void Show(WeifenLuo.WinFormsUI.Docking.DockState docState)
    {
        FormBase f = FormGlobals.Form_FindInTab(this);
        if (f == null)
        {
            m_initDialog = false;
            Init_Form();
            //Init_Form();
        }
        else
        {
            f.InitValue = this.InitValue;
            f.Recall_Form();
        }
        _IsLoading = false;
        if (f == null)
        {
            this.Show(FormGlobals.dockPanel, docState);
            FormGlobals.dockPanel.BringToFront();
        }
        else
        {
            f.Activate();
        }
    }

    #region "Properies"
    private bool _IsLoading = true;
    public bool IsLoading
    {
        get { return _IsLoading; }
        set { _IsLoading = value; }
    }

    private List<string> m_lstButtonPermission;
    protected bool ButtonPermission
    {
        get { return true; }
    }

    protected string UserName
    {
        get { return ""; }// FormGlobals.CS_USER_NAME; }
    }

    protected long UserId
    {
        get { return 0; }// FormGlobals.CS_USER_ID; }
    }

    //protected string[] UserRoles
    //{
    //    get { return FormGlobals.CS_USER_ROLES_CODE.Split(new char[] { ',' }); }
    //}

    private string _FormId = Guid.NewGuid().ToString();
    internal string FormId
    {
        get { return _FormId; }
    }

    private string _MenuName;
    public string MenuName
    {
        get { return _MenuName; }
        set { _MenuName = value; }
    }

    private object _InitValue;
    public object InitValue
    {
        get { return _InitValue; }
        set { _InitValue = value; }
    }

    private object _InputValue;
    public object InputValue
    {
        get { return _InputValue; }
        set { _InputValue = value; }
    }
    #endregion

    #region "Private function"

    private Button btnExit;
    private bool m_initDialog;

    public FormBase()
    {
        InitializeComponent();

        //Đặt lại Icon của form cho tất cả các form
        if(this.ShowIcon)
            this.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
    }


    private void Init_Form()
    {
        //this.BackColor = SystemColors.Control;


        //Init form control style
        //FormGlobals.Control_SetFlat(this);
        FormGlobals.Control_SetStyle(this);


        //Init track input value
        //Init_TrackInput();
        //Init command panel
        //Init command panel


        Control pnlCommand = FormGlobals.Find_Control(this, "pnlCommand") as Control;
        if ((pnlCommand != null))
        {
            FormGlobals.Panel_InitCommand(pnlCommand);
            //Set auto close
            string[] arrButton = new string[] {
            "Cancel",
            "Close",
            "Exit"
        };
            foreach (Control ctl in pnlCommand.Controls)
            {
                if (ctl is Button)
                {
                    if (arrButton.Contains(ctl.Name.Substring(3)))
                    {
                        btnExit = ctl as Button;
                        ctl.Click += Form_Exit;
                        btnExit.CausesValidation = false;
                    }
                    //
                    //FormGlobals.HotKey_Init(ctl);
                    //TrackInput_Button(ctl);
                }
            }
            //Init Button Permission
            if (!string.IsNullOrEmpty(this.UserName))
            {
                DataTable m_dtButton = App_Functions_Controller.Instance().ListButton(this.Name);
                //m_lstButtonPermission = FormGlobals.Control_SetPermission(pnlCommand, m_dtButton);
            }
        }

        //Init toolbar
        ToolStrip tsToolbar = FormGlobals.Find_Control(this, "tsToolbar") as ToolStrip;
        if ((tsToolbar != null))
        {
            foreach (ToolStripItem ctlChild in tsToolbar.Items)
            {
                if (ctlChild is PagerToolStripItem)
                {
                    ((PagerToolStripItem)ctlChild).PageIndex_Changed += PageIndex_Changed;
                }
                else if (ctlChild is ToolStripComboBox)
                {
                    //Combo_SetHandle(((ToolStripComboBox)ctlChild).ComboBox);
                }
                else if (ctlChild is ToolStripButton)
                {
                    //Hanlde khi focus đến toolstrip, nhấn enter thì tương dưng PerformClick
                    //HotKey_Init(ctlChild);
                    //Toolbar_SetImage(ctlChild);
                    //TrackInput_ToolStrip(ctlChild);
                }
            }
        }

        //Init input custom valid
        Control grbInput = (Control)FormGlobals.Find_Control(this, "grbInput");
        if ((grbInput != null))
        {
            Control_HandlerValid(grbInput);
            //chua chuyen sang
        }
        //
        if (m_initDialog)
        {
            this.Padding = new Padding(8);
            if ((btnExit != null))
            {
                btnExit.DialogResult = DialogResult.Cancel;
                btnExit.CausesValidation = false;
            }
        }
        else
        {
            this.Padding = new Padding(3, 3, 3, 8);
            if ((btnExit != null))
                btnExit.DialogResult = DialogResult.None;
        }

        //call form control init
        Init_Control();
        //init tab order
        Init_TabOrder();
        //init tab focus

        //finish loading
        _IsLoading = false;

        //
    }
        


    private TabOrderManager tom;//= new TabOrderManager();
    private void Init_TabOrder()
    {
        tom = new TabOrderManager(this);
        tom.SetTabOrder(TabOrderManager.TabScheme.AcrossFirst);
    }
    #endregion

    protected void Form_Exit(object sender, EventArgs e)
    {
        this.Close();
    }


    private Dictionary<string, MethodInvoker> _dicTimerCallback;
    private Dictionary<string, Timer> _dicTimerControl;
    public string Timer_Invoke(TimeSpan timeInterval, MethodInvoker callbackInvoke)
    {
        return Timer_Invoke(timeInterval, callbackInvoke, true);
    }
    private string Timer_Invoke(TimeSpan timeInterval, MethodInvoker callbackInvoke, bool limitTimer)
    {
        if (limitTimer && timeInterval.TotalSeconds < 10)
        {
            throw new ArgumentException("Interval must greater than or equal 10 seconds", "timeInterval");
        }
        if (_dicTimerCallback == null)
        {
            _dicTimerCallback = new Dictionary<string, MethodInvoker>();
            _dicTimerControl = new Dictionary<string, Timer>();
        }
        Timer timer = new Timer();
        timer.Tag = Guid.NewGuid().ToString();
        //
        _dicTimerCallback.Add(timer.Tag.ToString(), callbackInvoke);
        _dicTimerControl.Add(timer.Tag.ToString(), timer);
        //
        timer.Interval = Convert.ToInt32(timeInterval.TotalMilliseconds);
        timer.Tick += Timer_Tick;
        timer.Start();
        //
        return timer.Tag.ToString();
    }

    public void Timer_Revoke(string timerID)
    {
        if ((_dicTimerCallback != null) && _dicTimerCallback.ContainsKey(timerID))
        {
            _dicTimerCallback.Remove(timerID);
            _dicTimerControl[timerID].Stop();
            _dicTimerControl[timerID].Dispose();
            _dicTimerControl.Remove(timerID);
        }
        else
        {
            throw new Exception("Timer ID '" + timerID + "' not found in list");
        }
    }

    private void Timer_RevokeAll()
    {
        if (_dicTimerCallback == null)
            return;
        foreach (string timerID in _dicTimerCallback.Keys)
        {
            _dicTimerControl[timerID].Stop();
            _dicTimerControl[timerID].Dispose();
        }
        _dicTimerCallback.Clear();
        _dicTimerControl.Clear();
    }

    //Store in queue timer when form inactive
    private List<string> m_lstTimer = new List<string>();
    private void Timer_Tick(object sender, EventArgs e)
    {
        string sKey = ((Timer)sender).Tag.ToString();
        if (_dicTimerCallback.ContainsKey(sKey))
        {
            //
            if (m_lstTimer.Contains(sKey))
            {
                return;
            }
            else
            {
                m_lstTimer.Add(sKey);
            }
            if (!this.IsActivated)
                return;
            //
            try
            {
                _dicTimerCallback[sKey].Invoke();
            }
            catch
            {
                throw;
            }
            finally
            {
                m_lstTimer.Remove(sKey);
            }
        }
        else
        {
            ((Timer)sender).Stop();
            ((Timer)sender).Dispose();
        }
    }

    //=======================================================
    //Service provided by Telerik (www.telerik.com)
    //Conversion powered by NRefactory.
    //Twitter: @telerik
    //Facebook: facebook.com/telerik
    //=======================================================


    private bool m_IsActived;
    private Control firstFocusControl;
    /// <summary>
    /// Control đầu tiên sẽ được focus đến khi mở form
    /// Sau khi sự kiện FormBase_Activated
    /// </summary>
    public Control FirstFocusControl
    {
        get { return firstFocusControl; }
        set { firstFocusControl = value; }
    }

    private void FormBase_Activated(object sender, System.EventArgs e)
    {
        if (!m_IsActived)
        {
            m_IsActived = true;
            
            //Nếu đặt control focus đầu tiên, thì focus đến
            //Không thì mặc định focus đến control có thứ tự đầu tiên của form

            if (!IsLoading && firstFocusControl != null)
            {
                firstFocusControl.Focus();
            }
            else
            {
                FormGlobals.Control_FirstFocus(this);
            }
        }
        else
        {
            string sKey = null;
            while (m_lstTimer.Count > 0)
            {
                sKey = m_lstTimer[0];
                try
                {
                    _dicTimerCallback[sKey].Invoke();
                }
                catch
                {
                    throw;
                }
                finally
                {
                    m_lstTimer.Remove(sKey);
                }
            }
        }
    }

    protected new void Closed()
    {
        if ((_dicTimerCallback != null))
            _dicTimerCallback.Clear();
    }

    protected void Control_HandlerValid(params Control[] arrParent)
    {
        foreach (Control ctlParent in arrParent)
        {
            Control_HandlerValid(ctlParent);
        }
    }

    protected void Control_HandlerValid(Control ctlParent)
    {
        foreach (Control ctlChild in ctlParent.Controls)
        {
            if (ctlChild is TextBox || ctlChild is CheckBox || ctlChild is RadioButton || ctlChild is RadioButtonList)
            {
                ctlChild.Validated += Control_Validating;
            }
            else if (ctlChild.HasChildren)
            {
                Control_HandlerValid(ctlChild);
            }

            //Set color
            Color lastColorSaved = Color.Empty;
        //foreach (Control c in this.Controls)
        //{
            //Handle enter, focus control
            
        //}
            //}
        }
    }

    private void Control_Validating(object sender, System.EventArgs e)
    {
        Control ctlChild = sender as Control;
        FormGlobals.FormControlExt formExt = FormGlobals.Control_GetExtension(ctlChild);
        if (FormGlobals.Control_GetValue(ctlChild) == formExt.PrevValue)
            return;
        Control_Validated(sender, e);
        formExt.PrevValue = FormGlobals.Control_GetValue(ctlChild);
        FormGlobals.Control_SetExtension(ctlChild, formExt);
    }


    //-----------------------------------------------------------------------------------

    //Gán sự kiện bấm nút <- , -> để chuyển control, thay vì enter
    public void Textbox_SetKeyNextPreGroup(Control grb)
    {
        foreach (Control ctr in grb.Controls)
        {
            if (ctr.HasChildren)
                Textbox_SetKeyNextPreGroup(ctr);
            else
            {
                if (ctr is TextBox)
                    Textbox_SetKeyNextPre(ctr as TextBox);
            }
        }
    }

    public void Textbox_SetKeyNextPre(params TextBox[] txtObjs)
    {
        foreach (TextBox txt in txtObjs)
            Textbox_SetKeyNextPre(txt);
    }

    public void Textbox_SetKeyNextPre(TextBox txtObj)
    {
        txtObj.KeyDown += new KeyEventHandler(txtObj_KeyDown);
    }

    void txtObj_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Left || e.KeyCode == Keys.Up)
        {
            this.ProcessTabKey(false);
            ((TextBox)sender).SelectAll();
            e.Handled = true;
        }
        else if (e.KeyCode == Keys.Right || e.KeyCode == Keys.Down)
        {
            this.ProcessTabKey(true);
            ((TextBox)sender).SelectAll();
            e.Handled = true;
        }
        else
            base.OnKeyDown(e);
    }

}



